package com.wwinsoft.framework.entity.security;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.persistence.Version;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.FilterDef;
import org.hibernate.annotations.FilterJoinTable;
import org.hibernate.annotations.GenericGenerator;

import com.google.common.collect.Lists;
import com.wwinsoft.framework.entity.AssignedIDEntity;
import com.wwinsoft.framework.entity.AutoIdEntity;
import com.wwinsoft.framework.pojo.common.MenuTreeNode;
import com.wwinsoft.modules.utils.reflection.ConvertUtils;

/**
 * 角色.
 * <p/>
 * 注释见{@link User}.
 *
 * @author calvin
 */
@Entity
@Table(name = "ACT_ID_GROUP")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@FilterDef(name = "defaultAuthorityFilter")
public class Group extends AutoIdEntity implements MenuTreeNode {

    public static final String PREFIX_ROLE = "R_";
    public static final String TYPE_ROLE = "ROLE";
    public static final String PREFIX_DEPT = "D_";
    public static final String TYPE_DEPT = "DEPT";
    private String name;
    private String type;
    private Long parentId;
    
    /** 部门ID */
    private String deptId;
    /** 部门所属类别 */
    private Integer category;
    /** 版本 */
    protected Long revision;
    // <-- add by sevenSpend 2011-11-26 end
    
    private List<Authority> authorityList = Lists.newArrayList();

    private List<RoleAuthority> roleAuthorityList = Lists.newArrayList();

    private MenuTreeNode parent;
    private List<MenuTreeNode> children;

    private String orginDeptId;

    private List<Long> checkedAuthIds;


    public Group() {
    }

    @Column(name = "NAME_", nullable = false, unique = true)
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Column(name = "TYPE_")
    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    @Column(name = "ID_")
    public String getDeptId() {
		return deptId;
	}

	public void setDeptId(String deptId) {
		this.deptId = deptId;
	}

    @Column(name = "CATEGORY_")
    public Integer getCategory() {
        return category;
    }

    public void setCategory(Integer category) {
        this.category = category;
    }

    @Column(name = "REV_")
    @Version
    public Long getRevision() {
        return revision;
    }

    public void setRevision(Long revision) {
        this.revision = revision;
    }

    public Long getParentId() {
        return parentId;
    }

    public void setParentId(Long parentId) {
        this.parentId = parentId;
    }

    // <-- add by sevenSpend 2011-11-26 end

	@ManyToMany
    @FilterJoinTable(name = "defaultAuthorityFilter", condition = "type = 0")
    @JoinTable(name = "ACCT_ROLE_AUTHORITY", joinColumns = { @JoinColumn(name = "ROLE_ID") },
               inverseJoinColumns = { @JoinColumn(name = "AUTHORITY_ID") })
    @Fetch(FetchMode.SUBSELECT)
    @OrderBy("id")
    public List<Authority> getAuthorityList() {
        return authorityList;
    }

    @OneToMany(cascade = { CascadeType.MERGE}, fetch = FetchType.LAZY)
    @JoinColumn(name = "ROLE_ID",referencedColumnName="ID")
    public List<RoleAuthority> getRoleAuthorityList() {
        return roleAuthorityList;
    }

    public void setRoleAuthorityList(List<RoleAuthority> roleAuthorityList) {
        this.roleAuthorityList = roleAuthorityList;
    }

    public void setAuthorityList(List<Authority> authorityList) {
        this.authorityList = authorityList;
    }

    @Transient
    public String getAuthNames() {
        return ConvertUtils.convertElementPropertyToString(authorityList, "name", ", ");
    }

    @Transient
    @SuppressWarnings("unchecked")
    public List<Long> getAuthIds() {
        return ConvertUtils.convertElementPropertyToList(authorityList, "id");
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }

    public void popRoleBaseInfo() {
        // update by sevenSpend 2011-11-26 start -->
//    	setId(new StringBuilder().append(PREFIX_ROLE).append(name).toString());
    	setDeptId(new StringBuilder().append(PREFIX_ROLE).append(name).toString());
        // <-- update by sevenSpend 2011-11-26 end
        setType(TYPE_ROLE);
    }

    public void popDeptBaseInfo() {
        // <-- update by sevenSpend 2011-11-26 end
//    	setId(new StringBuilder().append(PREFIX_DEPT).append(name).toString());
    	setDeptId(new StringBuilder().append(PREFIX_DEPT).append(name).toString());
        // <-- update by sevenSpend 2011-11-26 end
        setType(TYPE_DEPT);
    }

    @Transient
    @Override
    public Long getParentNodeId() {
        return parentId;
    }

    @Transient
    @Override
    public String getNodeName() {
        return name;
    }

    @Transient
    @Override
    public String getNodeType() {
        return type;
    }

    @Transient
    @Override
    public MenuTreeNode getParent() {
        return parent;
    }

    @Override
    public void setParent(MenuTreeNode parent) {
        this.parent = parent;
    }

    @Transient
    @Override
    public List<MenuTreeNode> getChildren() {
        return children;
    }

    @Override
    public void addChild(MenuTreeNode child) {
        if (children == null) {
            children = Lists.newArrayList();
        }
        children.add(child);
    }

    @Transient
    @Override
    public Map getAttrMap() {
        HashMap map = new HashMap();
        map.put("name",name);
        return map;
    }

    @Transient
    public String getOrginDeptId() {
        return orginDeptId;
    }

    public void setOrginDeptId(String orginDeptId) {
        this.orginDeptId = orginDeptId;
    }

    @Transient
    public List<Long> getCheckedAuthIds() {
        return checkedAuthIds;
    }

    public void setCheckedAuthIds(List<Long> checkedAuthIds) {
        this.checkedAuthIds = checkedAuthIds;
    }
}
